<template>
	<view class="content-box">
		<!-- 顶部区域 -->
		<view class="header">
			<view class="u-flex">
				<image class="logo" src="/static/icon/logo.svg" mode="aspectFit"></image>
				<text class="text">TIES</text>
			</view>
			<view class="language-switch" @click="goToLanguagePage">
				<image class="language-icon" src="/static/image/home/yuyan.svg" mode="aspectFit"></image>
				<text>{{ t('language.' + locale) }}</text>
			</view>
		</view>

		<!-- 轮播图区域 -->
		<view class="banner-container">
			<!-- 动态渲染滚动图 -->
			<view v-if="bannerList.length > 0">
				<swiper indicator-dots=true autoplay=true>
					<swiper-item v-for="banner in bannerList" :key="banner.id">
						<image class="banner-image" :src="banner.url" mode="widthFix"></image>
					</swiper-item>
				</swiper>
			</view>
			<!-- 没有滚动图時顯示預設图片 -->
			<view v-else>
				<image class="banner-image" src="/static/image/home/top.png" mode="widthFix"></image>
			</view>
		</view>

		<!-- 功能按钮区域 -->
		<view class="function-buttons">
			<view class="function-row">
				<view class="function-item" @click="goRechange">
					<image class="function-icon" src="/static/image/home/chongzhi.svg" mode="aspectFit"></image>
					<text class="function-text">{{ $t('home.chongzhi') }}</text>
				</view>
				<view class="function-item" @click="goWithdraw">
					<image class="function-icon" src="/static/image/home/tixian.svg" mode="aspectFit"></image>
					<text class="function-text">{{ $t('home.tixian') }}</text>
				</view>
				<view class="function-item" @click="goFAQ">
					<image class="function-icon" src="/static/image/home/FAQ.svg" mode="aspectFit"></image>
					<text class="function-text">FAQ</text>
				</view>
				<view class="function-item" @click="goInvitation">
					<image class="function-icon" src="/static/image/home/yaoqing.svg" mode="aspectFit"></image>
					<text class="function-text">{{ $t('home.yaoqing') }}</text>
				</view>
			</view>
			<view class="function-row">
				<view class="function-item" @click="goRanking">
					<image class="function-icon" src="/static/image/home/paihangbang.svg" mode="aspectFit"></image>
					<text class="function-text">{{ $t('home.paihangbang') }}</text>
				</view>
				<view class="function-item" @click="goMessage">
					<image class="function-icon" src="/static/image/home/zhanneixin.svg" mode="aspectFit"></image>
					<text class="function-text">{{ $t('home.zhanneixin') }}</text>
				</view>
				<view class="function-item" @click="goNetworkDemo">
					<image class="function-icon" src="/static/image/home/FAQ.svg" mode="aspectFit"></image>
					<text class="function-text">网络演示</text>
				</view>
				<view class="function-item online-service" @click="goService">
					<view class="service-content">
						<text class="service-title">{{ $t('home.zaixiankefu') }}</text>
						<text class="service-desc">{{ $t('home.kefudesc') }}</text>
					</view>
					<image class="service-icon" src="/static/image/home/zaixiankefu.svg" mode="aspectFit"></image>
				</view>
			</view>
		</view>

		<!-- 公告区域 -->
		<view class="announcement" @mouseleave="handleAnnouncementLeave">
			<view class="announcement-content" @click="noticeClick" @mouseenter="announcementList.length > 0 && handleAnnouncementHover(announcementList[0])">
				<image class="announcement-icon" src="/static/image/home/laba.svg" mode="aspectFit"></image>
				<view class="announcement-right">
					<view class="announcement-title" v-if="currentAnnouncement">{{ currentAnnouncement.title || '公告' }}</view>
					<view class="announcement-title" v-else>公告</view>
				</view>
				<view class="announcement-time">
					<view class="announcement-date" v-if="currentAnnouncement">{{ formatDate(currentAnnouncement.createTime) }}</view>
					<view class="announcement-date" v-else>2025.01.01</view>
				</view>
			</view>
			<!-- 公告列表下拉菜单 -->
			<!-- <view v-if="announcementList.length > 0" class="announcement-list">
				<view v-for="(item, index) in announcementList.slice(0, 5)" :key="item.id" 
					class="announcement-list-item" 
					:class="{ active: hoveredAnnouncementId === item.id }"
					@mouseenter="handleAnnouncementHover(item)">
					<text class="announcement-list-title">{{ item.title }}</text>
					<text class="announcement-list-date">{{ formatDate(item.createTime) }}</text>
				</view>
			</view> -->
		</view>

		<!-- 产品推荐区域 -->
		<view class="product-section">
			<view class="section-header">
				<view class="section-title">
					<view class="title-bar"></view>{{ $t('home.productRecommend') }}
				</view>
				<!-- WebSocket连接状态指示器 -->
				<view class="ws-status" :class="{ 'connected': wsConnected, 'disconnected': !wsConnected }">
					<view class="status-dot"></view>
					<text class="status-text">{{ wsConnected ? '实时数据' : '连接中...' }}</text>
				</view>
			</view>

			<view class="product-list">
				<!-- 加载状态 -->
				<view v-if="loading" class="loading-container">
					<view class="loading-spinner"></view>
					<text class="loading-text">{{ $t('home.loading') || '加载中...' }}</text>
				</view>

				<!-- 动态产品列表 -->
				<view v-else-if="productList.length > 0" v-for="(product, index) in productList"
					:key="product.id || index" class="product-item"
					:class="{ 'offline': !wsConnected, 'updating': isRendering && renderQueue.length > 0 }"
					@click="goProdDetail(product)">
					<view class="product-header">
						<text class="product-name">{{ product.formattedName || product.name }}</text>
						<text class="product-pair">{{ product.formattedPair || product.code }}</text>
					</view>
					<view class="product-chart">
						<AreaSeriesItem :style="{ pointerEvents: 'none' }" :productId="product.id"
							:productCode="product.code || 'UNKNOWN'"
							:lineColor="index % 2 === 0 ? '#F7384F' : '#0DB364'" bottomColor="#fff"
							:upColor="index % 2 === 0 ? '#F7384F' : '#0DB364'"
							:containerAreaSeries="`homeContainerAreaSeries${index + 1}`"
							:dataAreaSeries="getKlineDataForProduct(product.id)" :lll="0.55" width="95" height="32">
						</AreaSeriesItem>
					</view>
					<view class="product-price">
						<text class="price-value">{{ product.price || '0.00' }}</text>
						<view class="price-change" :class="product.changePercent >= 0 ? 'up' : 'down'">
							<image
								:src="product.changePercent >= 0 ? '/static/icon/up-icon.svg' : '/static/icon/down-icon.svg'"
								class="price-icon"></image>
							<text>{{ formatChangePercent(product.changePercent) }}</text>
						</view>
					</view>
					<!-- 数据更新指示器 -->
					<view v-if="isRendering && renderQueue.length > 0" class="update-indicator">
						<view class="update-dot"></view>
					</view>
				</view>

				<!-- 无数据状态 -->
				<view v-else class="no-data-container">
					<image class="no-data-icon" src="/static/icon/no-data.svg" mode="aspectFit"></image>
					<text class="no-data-text">{{ $t('home.noProducts') || '暂无产品数据' }}</text>
				</view>
			</view>
		</view>

		<!-- 底部Tabbar -->
		<tabbar :currentTab="0"></tabbar>

		<!-- 公告弹窗 -->
		<uni-popup ref="popupNotice" type="center" :is-mask-click="true" @change="noticePopupChange"
			mask-background-color="rgba(0,0,0,0)">
			<view class="poupp-box" v-if="currentAnnouncement">
				<image class="title-icon" src="/static/image/home/laba.svg" mode="aspectFit"></image>
				<view class="title">{{ currentAnnouncement.title || $t('home.announcement') }}</view>
				<view class="text">{{ stripHtmlTags(currentAnnouncement.content) }}</view>
				<view class="text right">{{ formatDate(currentAnnouncement.createTime) }}</view>
			</view>
			<view class="poupp-box" v-else>
				<image class="title-icon" src="/static/image/home/laba.svg" mode="aspectFit"></image>
				<view class="title">{{ $t('home.announcement') }}</view>
				<view class="text">公告加载中...</view>
				<view class="text right">2025.01.01</view>
			</view>
		</uni-popup>
	</view>
</template>

<script setup>
import tabbar from '@/components/tabbar/tabbar.vue';
import AreaSeriesItem from "@/components/AreaSeriesItem/areaSeriesItem.vue";
import { ref, onMounted, onUnmounted, computed, nextTick } from 'vue';
import { useI18n } from 'vue-i18n';
import { incomeApi } from '@/utils/api.js';
import websocketService from '@/utils/websocket.js';
const { t, locale } = useI18n();

// 响应式数据
const productList = ref([]);
const loading = ref(true);
const wsConnected = ref(false);
const wsError = ref('');
const klineDataMap = ref(new Map());
const initialKlineDataMap = ref(new Map()); // 专门存储初始K线数据
const renderQueue = ref([]);
const isRendering = ref(false);
const announcementList = ref([]); // 公告列表
const currentAnnouncement = ref(null); // 当前选中的公告
const bannerList = ref([]); // 滚动图列表
const hoveredAnnouncementId = ref(null); // 当前悬停的公告ID
const popupNotice = ref(null); // 公告弹窗组件引用

// 模拟的WebSocket
let mockSocket = null;
let messageInterval = null;

// 格式化涨跌百分比
const formatChangePercent = (changePercent) => {
	if (changePercent === null || changePercent === undefined) return '0.00%';
	const num = parseFloat(changePercent);
	if (isNaN(num)) return '0.00%';
	const sign = num >= 0 ? '+' : '';
	return `${sign}${num.toFixed(2)}%`;
};

// 不会竞争的恢复日期格式
const formatDate = (timestamp) => {
	if (!timestamp) return '2025.01.01';
	const date = new Date(Number(timestamp));
	const year = date.getFullYear();
	const month = String(date.getMonth() + 1).padStart(2, '0');
	const day = String(date.getDate()).padStart(2, '0');
	return `${year}.${month}.${day}`;
};

// 执行 HTML 中的脚本标签
// 注：斾置根据应用是否支持HTML渲染
const stripHtmlTags = (html) => {
	if (!html) return '';
	const tmp = document.createElement('DIV');
	tmp.innerHTML = html;
	return tmp.textContent || tmp.innerText || '';
};

// 格式化产品代码
const formatProductCode = (code) => {
	if (!code || code === 'UNKNOWN') return { name: 'N/A', pair: 'N/A' };
	const upperCode = String(code).toUpperCase();
	const baseCurrencies = ['USDT', 'USD', 'BTC', 'ETH', 'BNB'];
	for (const base of baseCurrencies) {
		if (upperCode.endsWith(base)) {
			const name = upperCode.replace(base, '');
			return { name, pair: `${name}/${base}` };
		}
	}
	if (upperCode.length > 4) {
		const name = upperCode.slice(0, -4);
		const base = upperCode.slice(-4);
		return { name, pair: `${name}/${base}` };
	}
	return { name: upperCode, pair: upperCode };
};

// 获取K线数据（优先使用实时数据，如果没有则使用初始数据）
const getKlineDataForProduct = computed(() => (productId) => {
	const realTimeData = klineDataMap.value.get(productId);
	if (realTimeData && realTimeData.length > 0) {
		return realTimeData;
	}
	// 如果没有实时数据，返回初始数据
	const initialData = initialKlineDataMap.value.get(productId) || [];
	return initialData;
});

// 获取产品列表并初始化K线数据
const getProductList = async () => {
	loading.value = true;
	try {
		// 请求推荐产品接口，每页6条数据
		const res = await incomeApi.getGoodsStockPage({ pageNo: 1, pageSize: 6 })
		const list = res?.data?.list || [];
		productList.value = list.map(p => {
			const stockInfo = p.stockInfo || {};
			const market = stockInfo.market || {};

			// 使用 productCode 字段作为产品代码
			const code = p.productCode || stockInfo.code || stockInfo.symbol || 'UNKNOWN';
			const { name, pair } = formatProductCode(code);

			// 从 market 中获取最新价格和涨跌幅
			const lastPrice = market.lastPrice || market.close || '0';
			const changePercent = market.changePercent || '0%';

			// 移除百分号并转换为数字
			const changePercentNum = parseFloat(String(changePercent).replace('%', '').replace('+', ''));
			return {
				...p,
				id: p.id,
				code: code,
				price: parseFloat(lastPrice),
				changePercent: changePercentNum,
				formattedName: name,
				formattedPair: pair,
			};
		});

		console.log('处理后的产品列表:', productList.value);

		// 初始化 K 线数据：将 klines 转换成 {time: 毫秒时间戳, value: 数值} 格式（面积图）
		console.log('【开始初始化K线数据】遍历所有产品，将接口返回的klines数据转换格式并保存到两个Map');
		productList.value.forEach(p => {
			const klines = p.stockInfo?.klines || [];
			console.log(`【产品 ${p.code} (ID: ${p.id}) 的原始 klines 数据】`, klines);

			if (klines.length === 0) {
				console.warn(`【产品 ${p.code} 没有 klines 数据】`);
				initialKlineDataMap.value.set(p.id, []);
				klineDataMap.value.set(p.id, []);
				return;
			}

			// 转换 klines 数据格式
			// timestamp 是字符串格式的秒级时间戳，需要转换为毫秒
			// close 是字符串格式的收盘价，需要转换为数字
			const klineArr = klines.map(k => {
				// 时间戳：字符串秒级 -> 数字毫秒级
				const timeMs = Number(k.timestamp) * 1000;
				// 价格：字符串 -> 数字（使用收盘价 close）
				const value = Number(k.close);

				return {
					time: timeMs,
					value: value
				};
			}).filter(k => !isNaN(k.time) && !isNaN(k.value) && k.time > 0 && k.value > 0);

			console.log(`【产品 ${p.code} 转换后的 K 线数据】`, klineArr);
			console.log(`【产品 ${p.code} K 线数量：${klineArr.length}，示例数据：`, klineArr[0]);
			initialKlineDataMap.value.set(p.id, [...klineArr]); // 保存初始数据
			klineDataMap.value.set(p.id, [...klineArr]); // 同时设置为当前数据
		});

		console.log('【所有产品的 K 线数据已初始化】', {
			initialData: Array.from(initialKlineDataMap.value.entries()),
			currentData: Array.from(klineDataMap.value.entries())
		});
	} catch (e) {
		console.error('【/app-api/goods/stock/page 请求失败】', e);
		wsError.value = '加载产品数据失败，请稍后重试';

		// 兜底：使用模拟数据
		productList.value = [
			{ id: 26, code: 'BTC/USDT', price: 68000.5, changePercent: 1.25 },
			{ id: 2, code: 'ETH/USDT', price: 3500.75, changePercent: -0.52 },
			{ id: 3, code: 'DOT/USDT', price: 7.25, changePercent: 2.18 },
			{ id: 4, code: 'XRP/USDT', price: 0.52, changePercent: -1.15 },
			{ id: 5, code: 'TRX/USDT', price: 0.12, changePercent: 3.45 },
			{ id: 6, code: 'LINK/USDT', price: 18.5, changePercent: 0.88 },
		].map(p => {
			const { name, pair } = formatProductCode(p.code);
			return { ...p, formattedName: name, formattedPair: pair };
		});

		console.log('使用模拟数据:', productList.value);

		// 为模拟数据生成初始K线数据
		productList.value.forEach(p => {
			const now = Date.now();
			const mockKlines = [];
			// 生成最近7个数据点
			for (let i = 6; i >= 0; i--) {
				mockKlines.push({
					time: now - i * 60000, // 每分钟一个数据点
					value: p.price * (1 + (Math.random() - 0.5) * 0.02) // 价格上下浮动2%
				});
			}
			initialKlineDataMap.value.set(p.id, [...mockKlines]); // 保存初始数据
			klineDataMap.value.set(p.id, [...mockKlines]); // 同时设置为当前数据
			console.log(`【模拟数据】产品 ${p.code} (ID: ${p.id}) K线数据已初始化，数量: ${mockKlines.length}`);
		});
	}
	loading.value = false;

	// 确保初始数据渲染完成后再初始化WebSocket
	console.log('【初始化完成】所有产品的初始K线数据已准备，调用nextTick后延迟初始化WebSocket');
	await nextTick();
	console.log('【nextTick完成】现在延迟1000ms初始化WebSocket，确保图表已渲染');
	setTimeout(() => {
		console.log('【延迟初始化 WebSocket】确保所有图表都已渲染');
		initializeWebSocket();
	}, 1000);
};

// WebSocket消息处理器
const handleWebSocketMessage = (event) => {
	try {
		const message = JSON.parse(event.data);
		if (message.type === 'stock-kline-min1') {  // 修正消息类型为stock-kline-min1
			// 解析content字段（根据规范，content是字符串，需要解析两次）
			let content;
			try {
				// 第一次解析：将content字符串解析为JSON
				const contentStr = JSON.parse(message.content);
				console.log('第一次解析后的内容:', contentStr);
				
				// 第二次解析：将解析后的字符串再次解析为JSON对象
				content = JSON.parse(contentStr);
				console.log('第二次解析后的内容:', content);
			} catch (parseError) {
				console.error('解析content失败:', parseError);
				console.error('原始content:', message.content);
				return;
			}
			
			const productId = content.id;

			// 1. 更新价格和涨跌幅
			updateProductPrice(productId, content.market);

			// 2. 增量渲染K线（逐条追加）
			if (content.klines && content.klines.length > 0) {
				content.klines.forEach(kline => {
					// 时间戳转毫秒
					const timestamp = kline.timestamp || kline.time || 0;
					const timeMs = String(timestamp).length === 10
						? parseInt(timestamp) * 1000
						: parseInt(timestamp);

					// 获取价格值（使用收盘价 close）
					const value = parseFloat(kline.close || 0);

					if (!isNaN(timeMs) && !isNaN(value) && timeMs > 0 && value > 0) {
						// 只更新实时数据，不影响初始数据
						const arr = [...(klineDataMap.value.get(productId) || [])];

						// 检查是否已存在相同时间戳的数据，避免重复
						const existingIndex = arr.findIndex(item => item.time === timeMs);
						if (existingIndex >= 0) {
							// 更新已存在的数据点
							arr[existingIndex].value = value;
							
						} else {
							// 追加新数据点
							arr.push({ time: timeMs, value });
						}

						// 按时间排序并只保留最近100条
						arr.sort((a, b) => a.time - b.time);
						klineDataMap.value.set(productId, arr.slice(-100));
					}
				});
			}
		}
	} catch (error) {
		console.error('处理WebSocket消息失败:', error);
	}
};

// 更新产品价格
const updateProductPrice = (productId, marketData) => {
	const product = productList.value.find(p => p.id === productId);
	if (product) {
		const newPrice = parseFloat(marketData.lastPrice);
		const newChangePercent = parseFloat(String(marketData.changePercent).replace('%', ''));
		if (!isNaN(newPrice)) {
			console.log(`设置产品${productId}的新价格:`, newPrice.toFixed(2));
			product.price = newPrice.toFixed(2);
		}
		
		if (!isNaN(newChangePercent)) {
			console.log(`设置产品${productId}的新涨跌:`, newChangePercent);
			product.changePercent = newChangePercent;
		}
	}
};

// 初始化WebSocket
const initializeWebSocket = () => {
	console.log('初始化真实的WebSocket连接');
	
	// 延迟初始化真实的WebSocket连接
	setTimeout(() => {
		console.log('延迟初始化WebSocket连接');
		try {
			const connectionStatus = websocketService.getConnectionStatus();
			console.log('Home页面WebSocket连接状态:', connectionStatus);
			
			// 如果WebSocket已连接，注册消息监听器
			if (connectionStatus.isConnected) {
				console.log('WebSocket已连接，注册监听器');
				registerWebSocketListeners();
				wsConnected.value = true;
			} else {
				console.log('WebSocket未连接，尝试重新连接');
				// 尝试重新连接
				const token = uni.getStorageSync('access_token');
				console.log('获取到的token:', token ? '***' : 'null');
				if (token) {
					console.log('开始连接WebSocket');
					websocketService.connect(token)
						.then(() => {
							console.log('WebSocket重新连接成功');
							registerWebSocketListeners();
							wsConnected.value = true;
						})
						.catch(error => {
							console.error('WebSocket重新连接失败:', error);
							wsConnected.value = false;
							wsError.value = 'WebSocket连接失败';
						});
				} else {
					console.log('未找到token，无法连接WebSocket');
					wsConnected.value = false;
					wsError.value = '未登录，无法连接WebSocket';
				}
			}
		} catch (error) {
			console.error('Home页面WebSocket初始化失败:', error);
			wsConnected.value = false;
			wsError.value = 'WebSocket初始化失败';
		}
	}, 1000);
};

// 重试连接
const retryConnection = () => {
	console.log('尝试重新连接WebSocket');
	
	try {
		const token = uni.getStorageSync('access_token');
		console.log('重试连接获取到的token:', token ? '***' : 'null');
		
		if (token) {
			console.log('开始重试连接WebSocket');
			websocketService.connect(token)
				.then(() => {
					console.log('WebSocket重试连接成功');
					registerWebSocketListeners();
					wsConnected.value = true;
					wsError.value = '';
				})
				.catch(error => {
					console.error('WebSocket重试连接失败:', error);
					wsConnected.value = false;
					wsError.value = '重试连接失败';
				});
		} else {
			console.log('未找到token，无法连接WebSocket');
			wsConnected.value = false;
			wsError.value = '未登录，无法连接WebSocket';
		}
	} catch (error) {
		console.error('WebSocket重试连接异常:', error);
		wsConnected.value = false;
		wsError.value = '连接异常';
	}
};

onMounted(() => {
	console.log('Home页面onMounted开始执行');
	getProductList();
	getAnnouncementList(); // 获取公告信息
	getBannerList(); // 获取滚动图信息
	
	// 延迟初始化真实的WebSocket连接
	setTimeout(() => {
		console.log('开始初始化WebSocket连接');
		try {
			const connectionStatus = websocketService.getConnectionStatus();
			console.log('Home页面WebSocket连接状态:', connectionStatus);
			
			// 如果WebSocket已连接，注册消息监听器
			if (connectionStatus.isConnected) {
				console.log('WebSocket已连接，注册监听器');
				registerWebSocketListeners();
				wsConnected.value = true;
			} else {
				console.log('WebSocket未连接，尝试重新连接');
				// 尝试重新连接
				const token = uni.getStorageSync('access_token');
				console.log('获取到的token:', token ? '***' : 'null');
				if (token) {
					console.log('开始连接WebSocket');
					websocketService.connect(token)
						.then(() => {
							console.log('WebSocket重新连接成功');
							registerWebSocketListeners();
							wsConnected.value = true;
						})
						.catch(error => {
							console.error('WebSocket重新连接失败:', error);
							wsConnected.value = false;
							wsError.value = 'WebSocket连接失败';
						});
				} else {
					console.log('未找到token，无法连接WebSocket');
					wsConnected.value = false;
					wsError.value = '未登录，无法连接WebSocket';
				}
			}
		} catch (error) {
			console.error('Home页面WebSocket初始化失败:', error);
			wsConnected.value = false;
			wsError.value = 'WebSocket初始化失败';
		}
	}, 1500);
});

// 注册WebSocket消息监听器
const registerWebSocketListeners = () => {
	try {
		
		console.log('开始注册WebSocket监听器');
		
		// 移除旧的监听器
		if (window.homePageMessageHandler) {
			console.log('移除旧的消息监听器');
			websocketService.removeMessageListener(window.homePageMessageHandler);
		}
		
		// 移除旧的状态监听器
		if (window.homePageStatusHandler) {
			console.log('移除旧的状态监听器');
			websocketService.removeStatusListener(window.homePageStatusHandler);
		}
		
		// 创建状态变化监听器
		const statusHandler = (connected) => {
			console.log('WebSocket连接状态变化:', connected);
			wsConnected.value = connected;
			if (!connected) {
				wsError.value = 'WebSocket连接已断开';
			} else {
				wsError.value = '';
			}
		};
		
		// 添加状态监听器
		websocketService.addStatusListener(statusHandler);
		
		// 保存状态监听器引用到全局变量，以便后续移除
		window.homePageStatusHandler = statusHandler;
		
		// 创建新的消息监听器
		const messageHandler = (message) => {
			try {
				
				
				// 根据项目规范，只处理类型为stock-kline-min1的消息
				if (message.type === 'stock-kline-min1') {
					// 解析content字段（根据规范，content是字符串，需要解析两次）
					let content;
					try {
						// 第一次解析：将content字符串解析为JSON
						const contentStr = JSON.parse(message.content);
						// 第二次解析：将解析后的字符串再次解析为JSON对象
						content = JSON.parse(contentStr);
					} catch (parseError) {
						console.error('解析content失败:', parseError);
						console.error('原始content:', message.content);
						return;
					}
					
					const productId = content.id;
					const marketData = content.market;

					// 1. 更新价格和涨跌幅
					if (marketData) {
						
						updateProductPrice(productId, marketData);
					}

					// 2. 增量渲染K线（逐条追加）
					if (content.klines && content.klines.length > 0) {
						
						content.klines.forEach(kline => {
							// 时间戳转毫秒
							const timestamp = kline.timestamp || kline.time || 0;
							const timeMs = String(timestamp).length === 10
								? parseInt(timestamp) * 1000
								: parseInt(timestamp);

							// 获取价格值（使用收盘价 close）
							const value = parseFloat(kline.close || 0);

							if (!isNaN(timeMs) && !isNaN(value) && timeMs > 0 && value > 0) {
								// 只更新实时数据，不影响初始数据
								const arr = [...(klineDataMap.value.get(productId) || [])];

								// 检查是否已存在相同时间戳的数据，避免重复
								const existingIndex = arr.findIndex(item => item.time === timeMs);
								if (existingIndex >= 0) {
									// 更新已存在的数据点
									arr[existingIndex].value = value;
									
								} else {
									// 追加新数据点
									arr.push({ time: timeMs, value });
									
								}

								// 按时间排序并只保留最近100条
								arr.sort((a, b) => a.time - b.time);
								klineDataMap.value.set(productId, arr.slice(-100));

								
							}
						});
					}
				} else {
					
				}
			} catch (error) {
				console.error('Home页面处理WebSocket消息失败:', error);
				console.error('原始消息:', message);
			}
		};
		
		// 添加消息监听器
		websocketService.addMessageListener(messageHandler);
		
		// 保存监听器引用到全局变量，以便后续移除
		window.homePageMessageHandler = messageHandler;
		
		console.log('Home页面WebSocket监听器已注册');
		
		// 检查WebSocket连接状态
		const connectionStatus = websocketService.getConnectionStatus();
		console.log('检查WebSocket连接状态:', connectionStatus);
		wsConnected.value = connectionStatus.isConnected;
		if (connectionStatus.isConnected) {
			wsError.value = '';
		} else {
			wsError.value = 'WebSocket未连接';
		}
	} catch (error) {
		console.error('Home页面注册WebSocket监听器失败:', error);
		wsConnected.value = false;
		wsError.value = 'WebSocket监听器注册失败';
	}
};

onUnmounted(() => {
	// 移除WebSocket监听器
	try {
		// 移除消息监听器
		if (window.homePageMessageHandler) {
			websocketService.removeMessageListener(window.homePageMessageHandler);
			console.log('Home页面WebSocket消息监听器已移除');
		}
		
		// 移除状态监听器
		if (window.homePageStatusHandler) {
			websocketService.removeStatusListener(window.homePageStatusHandler);
			console.log('Home页面WebSocket状态监听器已移除');
		}
	} catch (error) {
		console.error('Home页面移除WebSocket监听器失败:', error);
	}
});

// 页面跳转函数 ...
const goToLanguagePage = () => uni.navigateTo({ url: '/pages/language/language' });
const goRechange = () => uni.navigateTo({ url: '/pages/recharge/recharge' });
const goWithdraw = () => uni.navigateTo({ url: '/pages/withdraw/withdraw' });
const goFAQ = () => uni.navigateTo({ url: '/pages/faq/Faq' });
const goInvitation = () => uni.navigateTo({ url: '/pages/invitation/invitation' });
const goRanking = () => uni.navigateTo({ url: '/pages/ranking/ranking' });
const goMessage = () => uni.navigateTo({ url: '/pages/message/message' });
const goNetworkDemo = () => uni.navigateTo({ url: '/pages/networkDemo/networkDemo' });
const goService = () => uni.navigateTo({ url: '/pages/service/service' });
const noticePopupChange = (e) => {
	/* 弹窗状态变化回调，目前可留空 */
};
const noticeClick = () => {
	if (popupNotice.value) {
		popupNotice.value.open();
	} else {
		console.error('popupNotice ref not initialized');
	}
};
const goProdDetail = (product) => uni.navigateTo({ url: `/pages/market/details?id=${product.id}` });

// 获取公告列表
const getAnnouncementList = async () => {
	try {
		const res = await incomeApi.getJournalismContent({
			pageNo: 1,
			pageSize: 15,
			categoryId: 11
		});
		if (res?.data?.list && res.data.list.length > 0) {
			announcementList.value = res.data.list;
			// 优先显示第一条公告
			currentAnnouncement.value = announcementList.value[0];
		}
	} catch (error) {
		console.error('【/app-api/journalism/content/page 请求失败】', error);
	}
};

// 获取滚动图列表
const getBannerList = async () => {
	try {
		const res = await incomeApi.getJournalismBanner({
			pageNo: 1,
			pageSize: 15,
			categoryId: 13
		});
		if (res?.data?.list && res.data.list.length > 0) {
			bannerList.value = res.data.list;
		}
	} catch (error) {
		console.error('【/app-api/journalism/banner/page 请求失败】', error);
	}
};

// 公告轮恢处理函数
const handleAnnouncementHover = (announcement) => {
	currentAnnouncement.value = announcement;
	hoveredAnnouncementId.value = announcement.id;
};

// 公告离开处理函数
const handleAnnouncementLeave = () => {
	if (announcementList.value.length > 0) {
		// 恢复为第一条公告
		currentAnnouncement.value = announcementList.value[0];
		hoveredAnnouncementId.value = announcementList.value[0].id;
	}
};
</script>

<style scoped lang="scss">
.poupp-box {
	width: 627.94rpx;
	height: 575.61rpx;
	border-radius: 52.33rpx;
	background: rgba(255, 255, 255, .7);
	backdrop-filter: blur(10.47rpx);
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	color: #000;

	.title-icon {
		margin: 59.31rpx 0 31.39rpx;
		width: 48.84rpx;
		height: 48.84rpx;
	}

	.title {
		font-size: 27.91rpx;
		font-weight: 700;
		padding: 0 13.95rpx;
		margin-bottom: 38.37rpx;
	}

	.text {
		font-size: 24.42rpx;
		font-weight: 300;
		margin-bottom: 27.9rpx;
		text-align: left;
		width: 519.8rpx;

		&.right {
			text-align: right;
		}
	}
}

.content-box {
	min-height: 100vh;
	background-color: #F5F6FA;
	padding-bottom: 100rpx;
	padding: 20rpx 41.81rpx;
}

/* 顶部区域样式 */
.header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	background-color: #F5F6FA;
	margin-bottom: 24.84rpx;
	padding-top: env(safe-area-inset-top);
	padding-top: constant(safe-area-inset-top);

	.text {
		background-image: linear-gradient(90deg, rgba(11, 187, 160, 1) 0%, rgba(8, 166, 179, 1) 50%, rgba(2, 121, 219, 1) 100%);
		/** 文本1 */
		font-size: 31.4rpx;
		font-weight: 700;
		-webkit-background-clip: text;
		/* 裁剪背景到文字 */
		color: transparent;
		/* 文字颜色设置为透明，以便显示背景颜色 */
	}
}

.logo {
	width: 80rpx;
	height: 40rpx;
}

.language-switch {
	display: flex;
	align-items: center;
	font-size: 24.42rpx;
	font-weight: 500;
	color: #333;
}

.language-icon {
	width: 27.91rpx;
	height: 27.91rpx;
	margin-right: 8rpx;
}

/* 轮播图区域样式 */
.banner-container {
	position: relative;
	margin: 0 auto;
}

.banner-image {
	width: 100%;
	height: auto;
}

/* 功能按钮区域样式 */
.function-buttons {
	background-color: #F5F6FA;
	border-radius: 20rpx;
	margin: 20rpx 0;
}

.function-row {
	display: flex;
	justify-content: space-between;
	margin-bottom: 20.91rpx;
	gap: 32.33rpx;
}

.function-row:last-child {
	margin-bottom: 0;
}

.function-item {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	width: 139.53rpx;
	height: 139.53rpx;
	background-color: #FFFFFF;
	border-radius: 20rpx;
	margin-right: 10rpx;
	box-sizing: border-box;
}

.function-row .function-item:last-child {
	margin-right: 0;
}

.function-icon {
	width: 61.05rpx;
	height: 61.05rpx;
}

.function-text {
	font-size: 21rpx;
	font-weight: 500;
	color: #333;
}

.online-service {
	width: 323.44rpx;
	flex-direction: row;
	justify-content: space-between;
	padding: 0 30rpx;
}

.service-content {
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.service-title {
	font-size: 21rpx;
	color: #333;
	font-weight: 500;
	margin-bottom: 10.45rpx;
}

.service-desc {
	font-size: 17.44rpx;
	font-weight: 500;
	color: #666;
}

.service-icon {
	width: 95.93rpx;
	height: 93.62rpx;
}

/* 公告区域样式 */
.announcement {
	margin: 20rpx 0 0;
	padding: 20rpx 40.07rpx;
	background-color: #FFFFFF;
	border-radius: 20rpx;
	position: relative;
}

.announcement-content {
	display: flex;
	align-items: center;
	justify-content: space-between;
}

.announcement-icon {
	width: 40rpx;
	height: 40rpx;
	min-width: 40rpx;
	min-height: 40rpx;
	margin-right: 24.84rpx;
}

.announcement-right {
	flex: 1;
	max-width: calc(100% - 80rpx);
	display: flex;
	flex-direction: column;
}

.announcement-title {
	font-size: 24.42rpx;
	font-weight: 500;
	color: #333;
	margin-bottom: 5rpx;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	max-width: 300rpx;

	span {
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;
	}
}

.announcement-time {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	justify-content: center;
	white-space: nowrap;
}

.announcement-date {
	font-size: 24.42rpx;
	font-weight: 400;
	color: #666;
}

/* 公告列表下拉菜单样式 */
.announcement-list {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	background-color: #FFFFFF;
	border-radius: 0 0 20rpx 20rpx;
	box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1);
	max-height: 300rpx;
	overflow-y: auto;
	z-index: 10;
}

.announcement-list-item {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 15rpx 20rpx;
	border-bottom: 1rpx solid #f0f0f0;
	cursor: pointer;
	transition: all 0.3s ease;
}

.announcement-list-item:hover,
.announcement-list-item.active {
	background-color: #f5f5f5;
	padding-left: 25rpx;
}

.announcement-list-title {
	font-size: 20.93rpx;
	font-weight: 500;
	color: #333;
	flex: 1;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.announcement-list-date {
	font-size: 18rpx;
	color: #999;
	margin-left: 10rpx;
	white-space: nowrap;
}

/* 产品推荐区域样式 */
.product-section {}

.section-title {
	font-size: 27.91rpx;
	font-weight: 500;
	color: #333;
	display: flex;
	align-items: center;
	margin: 43.55rpx 0;
}

.title-bar {
	width: 6.98rpx;
	height: 43.6rpx;
	border-radius: 5.23rpx;
	background: #0278DC;
	margin-right: 17.42rpx;
}

.product-list {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	padding-bottom: 120rpx;
}

.product-item {
	width: 209.3rpx;
	height: 286.05rpx;
	border-radius: 17.44rpx;
	background: #FFFFFF;
	box-shadow: 2rpx 2rpx 8rpx -4rpx #A19D9D;
	padding: 20.91rpx 33.1rpx;
	margin-bottom: 31.36rpx;
	box-sizing: border-box;

	a {
		display: none !important;
	}

	::v-deep a {
		display: none !important;
	}

	:deep(a) {
		display: none !important;
	}
}

.product-chart {
	margin-left: -23.1rpx;
	margin-bottom: 60rpx;
	height: 32rpx;

	a {
		display: none !important;
	}

	::v-deep a {
		display: none !important;
	}

	:deep(a) {
		display: none !important;
	}
}

.product-header {
	display: flex;
	flex-direction: column;
	margin-bottom: 10rpx;
}

.product-name {
	font-size: 27.91rpx;
	font-weight: 500;
	color: #333;
}

.product-pair {
	font-size: 20.93rpx;
	font-weight: 500;
	color: #666;
}


.chart-image {
	width: 100%;
	height: 80rpx;
}

.product-price {
	display: flex;
	justify-content: space-between;
	align-items: center;
	flex-direction: column;
}

.price-value {
	font-size: 20.93rpx;
	font-weight: 500;
	color: #333;
	margin-top: 10rpx;
}

.price-change {
	font-size: 20.93rpx;
	font-weight: 500;
	display: flex;
	align-items: center;
	gap: 6.97rpx;
}

.price-icon {
	width: 24.42rpx;
	height: 24.42rpx;
}

.price-change.up {
	color: #0DB364;
}

.price-change.down {
	color: #F7384F;
}

/* 加载状态和无数据状态样式 */
.loading-container,
.no-data-container {
	display: flex;
	justify-content: center;
	align-items: center;
	width: 100%;
	height: 200rpx;
	color: #666;
	font-size: 24rpx;
	flex-direction: column;
}

.loading-spinner {
	width: 40rpx;
	height: 40rpx;
	border: 3rpx solid #f3f3f3;
	border-top: 3rpx solid #0278DC;
	border-radius: 50%;
	animation: spin 1s linear infinite;
	margin-bottom: 20rpx;
}

@keyframes spin {
	0% {
		transform: rotate(0deg);
	}

	100% {
		transform: rotate(360deg);
	}
}

.loading-text,
.no-data-text {
	font-size: 24rpx;
	color: #666;
	margin-top: 10rpx;
}

.no-data-icon,
.error-icon {
	width: 60rpx;
	height: 60rpx;
	margin-bottom: 20rpx;
	opacity: 0.5;
}

/* 错误状态样式 */
.error-container {
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	width: 100%;
	height: 200rpx;
	padding: 40rpx;
	box-sizing: border-box;
}

.error-text {
	font-size: 24rpx;
	color: #F7384F;
	margin-bottom: 20rpx;
	text-align: center;
}

.retry-button {
	background: #0278DC;
	color: white;
	border: none;
	border-radius: 10rpx;
	padding: 15rpx 30rpx;
	font-size: 24rpx;
	cursor: pointer;
}

.retry-button:hover {
	background: #0266c2;
}

/* WebSocket连接状态指示器 */
.section-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin: 43.55rpx 0;
}

.ws-status {
	display: flex;
	align-items: center;
	font-size: 20rpx;
	padding: 8rpx 16rpx;
	border-radius: 20rpx;
	background: #f5f5f5;
	transition: all 0.3s ease;
}

.ws-status.connected {
	background: #e8f5e8;
	color: #0DB364;
}

.ws-status.disconnected {
	background: #ffeaea;
	color: #F7384F;
}

.status-dot {
	width: 12rpx;
	height: 12rpx;
	border-radius: 50%;
	margin-right: 8rpx;
	animation: pulse 2s infinite;
}

.ws-status.connected .status-dot {
	background: #0DB364;
}

.ws-status.disconnected .status-dot {
	background: #F7384F;
}

@keyframes pulse {
	0% {
		opacity: 1;
	}

	50% {
		opacity: 0.5;
	}

	100% {
		opacity: 1;
	}
}

.status-text {
	font-size: 20rpx;
	font-weight: 500;
}

/* 数据更新指示器 */
.product-item {
	position: relative;
}

.update-indicator {
	position: absolute;
	top: 10rpx;
	right: 10rpx;
	width: 8rpx;
	height: 8rpx;
	background: #0278DC;
	border-radius: 50%;
	animation: updatePulse 1s infinite;
}

@keyframes updatePulse {
	0% {
		transform: scale(1);
		opacity: 1;
	}

	50% {
		transform: scale(1.5);
		opacity: 0.7;
	}

	100% {
		transform: scale(1);
		opacity: 1;
	}
}

.product-item.updating {
	animation: subtleGlow 2s ease-in-out infinite alternate;
}

@keyframes subtleGlow {
	0% {
		box-shadow: 2rpx 2rpx 8rpx -4rpx #A19D9D;
	}

	100% {
		box-shadow: 2rpx 2rpx 12rpx -2rpx #0278DC;
	}
}
</style>
